<!--
 * @Description: 编辑弹窗
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2021-12-15 10:37:22
 * @LastEditTime: 2025-04-02 11:52:59
-->
<template>
	<el-dialog class="form-dialog" header-class="edit-header" :modelValue="modelValue"
		@update:modelValue="$emit('update:modelValue', $event)" :title="title" @open="open" @closed="closed" draggable
		center>
		<div v-loading="loading">
			<myForm ref="myFormRef" v-model="formParams" :options="options" :showSearchBtn="false" :inline="false"
				inputWidth="100%" :labelWidth="labelWidth">
				<template v-for="item in options.filter((o) => o.slot)" :key="item.key" v-slot:[item.slot]>
					<slot :name="item.slot" :val="formParams" />
				</template>
			</myForm>
		</div>
		<template #footer>
			<div class="dialog-footer">
				<el-button v-for="(item, ind) in btns" :key="item.name" plain :type="item.type"
					@click="bindBtnTap(ind, item.validate)">{{ item.name }}</el-button>
			</div>
		</template>
	</el-dialog>
</template>

<script lang="ts" setup>
	import { PropType, ref, watch } from "vue";
	import myForm from "../myForm/index.vue";
	import { IFormOption } from "../myForm/type";

	interface Ibtn {
		name : string;
		type : "default" | "primary" | "success" | "info" | "warning" | "danger";
		validate ?: boolean;
	}

	const props = defineProps({
		// 弹窗显隐
		modelValue: {
			type: Boolean,
			require: true,
			default: false
		},
		// 弹窗标题
		title: {
			type: String,
			default: "编辑"
		},
		// 默认距顶部距离
		top: {
			type: [String, Number],
			default: "20%"
		},
		// 表单项配置选项
		options: {
			type: Array as PropType<IFormOption[]>,
			require: true,
			default: () => []
		},
		// 表单数据
		params: {
			type: Object as PropType<Record<any, any>>,
			require: true,
			default: () => ({})
		},
		// 需要监听的字段变化
		watchFields: {
			type: Array,
			require: false,
			default: () => []
		},
		// loading
		loading: {
			type: Boolean,
			default: false
		},
		labelWidth: {
			type: String,
			require: false,
			default: "100px"
		},
		btns: {
			type: Array as PropType<Ibtn[]>,
			require: false,
			default: () => [
				{
					name: "取消",
					type: "default",
					validate: false
				},
				{
					name: "确认",
					type: "primary",
					validate: true
				}
			]
		}
	});

	// emit
	const emit = defineEmits(["update:modelValue", "submit", "change"]);

	// 表单对象
	const myFormRef = ref();
	// 中转表单数据
	const formParams = ref({} as Record<any, any>);

	// 按钮
	const bindBtnTap = (ind : number, validate : boolean) => {
		// 验证
		if (validate) {
			myFormRef.value.elForm.validate((valid : any) => {
				if (valid) {
					emit("submit", ind, JSON.parse(JSON.stringify(formParams.value)));
					// emit("update:modelValue", false);
				} else {
					return false;
				}
			});
		} else {
			emit("submit", ind, JSON.parse(JSON.stringify(formParams.value)));
			emit("update:modelValue", false);
		}
	};

	// 弹窗关闭完成
	const closed = () => {
		// 清除验证提示
		myFormRef.value.elForm.resetFields();
		// 清空表单信息
		formParams.value = {};
	};

	watch(
		() => props.params,
		(newVal) => {
			// 合并
			Object.assign(formParams.value, newVal);
		},
		{ deep: true, immediate: true } // 深度监听
	);

	// 弹窗触发open
	const open = () => {
		// 初始化值
		props.options.forEach((item) => {
			formParams.value[item.key] = item.default ? item.default : props.params[item.key];
		});
		// 合并
		// Object.assign(formParams.value, props.params);

		// 监听
		if (props.watchFields.length) {
			props.watchFields.forEach((field : any) => {
				watch(
					() => formParams.value[field],
					(val) => {
						emit("change", field, val, formParams);
					},
					{ deep: true }
				);
			});
		}
	};
</script>

<style lang="less" scoped>
	.edit-header {
		text-align: left !important;
	}

	.dialog-footer {
		text-align: right !important;
	}
</style>
<style>
	.form-dialog {
		width: 35% !important;
		min-width: 500px !important;

		.el-form--inline .el-form-item {
			margin-right: 20px;
		}
	}
</style>